'use client';

import useToast from '@/hooks/useToast';
import {
  type ChangeEvent,
  type FormEvent,
  useContext,
  useEffect,
  useState,
} from 'react';
import type {
  IDifference,
  IPagination,
  ISection,
  ISectionDetails,
  IUploadSectionCover,
} from '@/interfaces';
import { useMutation } from '@tanstack/react-query';
import { updateSection, uploadSectionCover } from '@/services/api';
import diff from 'microdiff';
import { getDiffData, isHttpOrHttps, isNum } from '@/lib/tool';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import Box from '@/app/[locale]/admin/common/box';
import { AppContext } from '@/contexts/app';
import Image from 'next/image';
import Spinner from '@/app/[locale]/component/spinner/spinner';
import type { PrefixedTTranslatedFields } from '@/lib/dictionaries';

export default function UpdateSectionInfo({
  source,
  sections,
  translatedFields,
}: {
  source: ISectionDetails;
  sections: IPagination<ISection>;
  translatedFields: PrefixedTTranslatedFields<'sectionAdminPage'>;
}) {
  const { show } = useToast();
  const [form, setForm] = useState<{
    name: string;
    sort: number;
    cover: string;
    overview: string;
    uploadCover: string;
    uploadCoverFile: Blob | null;
    uploadCoverObjectUrl: string;
  }>({
    name: source.basic.name,
    sort: source.basic.sort,
    cover: source.basic.cover || '',
    overview: source.basic.overview || '',
    uploadCover: '',
    uploadCoverFile: null,
    uploadCoverObjectUrl: '',
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const context = useContext(AppContext);
  const metadata = context.metadata;
  const [isPreviewCover, setIsPreviewCover] = useState(false);
  const [isDisabledSave, setIsDisabledSave] = useState(true);

  const updateSectionMutation = useMutation(updateSection);
  const uploadSectionCoverMutation = useMutation(uploadSectionCover);

  useEffect(() => {
    const diffData = diff(
      {
        name: source.basic.name,
        sort: source.basic.sort,
        cover: source.basic.cover || '',
        overview: source.basic.overview || '',
      },
      {
        name: form.name,
        sort: form.sort,
        cover: form.cover,
        overview: form.overview,
      },
    );
    setDifferenceData(diffData);
    setIsDisabledSave(diffData.length === 0);
  }, [form, source]);

  function checkName(name?: string) {
    if (
      (name && name === source.basic.name) ||
      sections.content.find((item) => item.name === name)
    ) {
      throw translatedFields.updateInfoPage.nameDuplicated;
    }
  }

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      const id = source.basic.id;
      const data = getDiffData(differenceData);

      checkName(data.name);

      await updateSectionMutation.mutateAsync({
        id,
        data,
      });

      show({
        type: 'SUCCESS',
        message: translatedFields.updateInfoPage.updatesCompleted,
      });
    } catch (e) {
      updateSectionMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    } finally {
      setDifferenceData([]);
    }
  }

  async function onClickUploadCover() {
    try {
      const uploadCoverFile = form.uploadCoverFile;
      if (!uploadCoverFile) {
        show({
          type: 'DANGER',
          message: '请选择封面文件后再上传',
        });
        return;
      }

      const { urls } = (await uploadSectionCoverMutation.mutateAsync({
        id: source.basic.id,
        data: {
          file: uploadCoverFile,
        },
      })) as IUploadSectionCover;

      if (form.uploadCoverObjectUrl) {
        URL.revokeObjectURL(form.uploadCoverObjectUrl);
      }

      setForm({
        ...form,
        cover: metadata!.env.APP_OSS_SERVER + urls.default,
        uploadCover: '',
        uploadCoverFile: null,
        uploadCoverObjectUrl: '',
      });

      show({
        type: 'SUCCESS',
        message: '上传完成',
      });
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickCloseCoverFile() {
    if (form.uploadCoverObjectUrl) {
      URL.revokeObjectURL(form.uploadCoverObjectUrl);
    }

    setForm({
      ...form,
      uploadCover: '',
      uploadCoverFile: null,
      uploadCoverObjectUrl: '',
    });
    setIsPreviewCover(false);
  }

  function onClickPreviewCover() {
    setIsPreviewCover(!isPreviewCover);
  }

  function onChangeForm(
    e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'uploadCover') {
      if (form.uploadCoverObjectUrl) {
        URL.revokeObjectURL(form.uploadCoverObjectUrl);
      }

      const files = (e.target as HTMLInputElement).files;
      if (!files) {
        return;
      }

      const file = files[0];
      setForm({
        ...form,
        uploadCover: value,
        uploadCoverFile: file,
        uploadCoverObjectUrl: URL.createObjectURL(file),
      });
    } else if (name === 'sort') {
      setForm({ ...form, sort: isNum(value) ? parseInt(value) : 0 });
    } else {
      setForm({ ...form, [name]: value });
    }
  }

  return (
    <Box>
      <form onSubmit={onClickSave} className="vstack gap-4">
        <div>
          <label className="form-label">
            {translatedFields.updateInfoPage.name}
          </label>
          <input
            type="text"
            className="form-control"
            name="name"
            value={form.name}
            onChange={onChangeForm}
            aria-describedby="name"
            placeholder={translatedFields.updateInfoPage.pleaseEnterName}
          />
        </div>

        <div>
          <div>
            <label className="form-label">
              {translatedFields.updateInfoPage.cover}
            </label>
            <textarea
              className="form-control"
              name="cover"
              value={form.cover}
              onChange={onChangeForm}
              rows={1}
              placeholder={translatedFields.updateInfoPage.pleaseEnterCover}
            ></textarea>
          </div>

          <div className="my-2 d-flex align-items-center">
            <div className="input-group align-items-center">
              <input
                type="file"
                accept="image/*"
                className="form-control"
                name="uploadCover"
                value={form.uploadCover}
                onChange={onChangeForm}
                aria-label="Upload"
              />
              <button
                disabled={uploadSectionCoverMutation.isLoading}
                onClick={onClickUploadCover}
                className="btn btn-outline-secondary"
                type="button"
              >
                {uploadSectionCoverMutation.isLoading && (
                  <span
                    className="spinner-border spinner-border-sm me-2"
                    role="status"
                    aria-hidden="true"
                  ></span>
                )}
                {translatedFields.updateInfoPage.upload}
              </button>
              <button
                type="button"
                onClick={onClickPreviewCover}
                className="btn btn-outline-secondary"
              >
                {isPreviewCover
                  ? translatedFields.updateInfoPage.cancelPreview
                  : translatedFields.updateInfoPage.preview}
              </button>
              {form.uploadCoverObjectUrl && (
                <button
                  type="button"
                  onClick={onClickCloseCoverFile}
                  className="btn-close ms-3"
                  aria-label="Close"
                ></button>
              )}
            </div>
          </div>

          {isPreviewCover && metadata && (
            <>
              {form.uploadCoverObjectUrl || form.cover ? (
                <div className="hstack gap-4">
                  <div
                    style={{ maxWidth: 142, maxHeight: 80 }}
                    className="ratio ratio-16x9"
                  >
                    <Image
                      width={142}
                      height={80}
                      className="object-fit-contain"
                      src={
                        form.uploadCoverObjectUrl
                          ? form.uploadCoverObjectUrl
                          : isHttpOrHttps(form.cover)
                          ? form.cover
                          : metadata.env.APP_OSS_SERVER + form.cover
                      }
                      alt="cover"
                    />
                  </div>
                  <div
                    style={{ maxWidth: 260, maxHeight: 146 }}
                    className="ratio ratio-16x9"
                  >
                    <Image
                      width={260}
                      height={146}
                      className="object-fit-contain"
                      src={
                        form.uploadCoverObjectUrl
                          ? form.uploadCoverObjectUrl
                          : isHttpOrHttps(form.cover)
                          ? form.cover
                          : metadata.env.APP_OSS_SERVER + form.cover
                      }
                      alt="cover"
                    />
                  </div>
                  <div
                    style={{
                      maxWidth: 378,
                      maxHeight: 213,
                    }}
                    className="ratio ratio-16x9"
                  >
                    <Image
                      width={378}
                      height={213}
                      className="object-fit-contain"
                      src={
                        form.uploadCoverObjectUrl
                          ? form.uploadCoverObjectUrl
                          : isHttpOrHttps(form.cover)
                          ? form.cover
                          : metadata.env.APP_OSS_SERVER + form.cover
                      }
                      alt="cover"
                    />
                  </div>
                </div>
              ) : (
                <Nodata />
              )}
            </>
          )}
        </div>

        <div>
          <label className="form-label">
            <span>{translatedFields.updateInfoPage.overview}</span>
            {form.overview && (
              <span className="text-secondary user-select-none">
                ({translatedFields.updateInfoPage.overviewLen}：
                {form.overview.length})
              </span>
            )}
          </label>
          <textarea
            className="form-control"
            name="overview"
            value={form.overview}
            onChange={onChangeForm}
            aria-describedby="overview"
            rows={2}
            placeholder={translatedFields.updateInfoPage.pleaseEnterOverview}
          />
        </div>

        <div>
          <label className="form-label">
            {translatedFields.updateInfoPage.sort}
          </label>
          <input
            type="number"
            min={0}
            className="form-control"
            name="sort"
            value={form.sort}
            onChange={onChangeForm}
            aria-describedby="sort"
            placeholder={translatedFields.updateInfoPage.pleaseEnterSort}
          />
        </div>

        <button
          type="submit"
          disabled={updateSectionMutation.isLoading || isDisabledSave}
          className="btn btn-success col col-lg-2 my-4"
        >
          {updateSectionMutation.isLoading && <Spinner classs="me-2" />}
          {translatedFields.updateInfoPage.update}
        </button>
      </form>
    </Box>
  );
}
